/* panel.cc
* This file is part of ncursesxx library
* Copyright (c) 2003,2004 by Stanislav Ievlev
*
* This file is covered by the GNU Library General Public License,
* which should be included with libncursesxx as the file COPYING.
*/
#include <algorithm>
#include <functional>
#include <stdexcept>

#include <iostream>

#include <ncurses/assert.hh>
#include <ncurses/panel.hh>

//not using namespace, 'cause curses already have struct with name panel
ncurses::panel::panel(panel *parent):
		window(),
		panel_(0),
		parent_(parent)
{
	//create panel object
	panel_ = ::new_panel(win());
	if (!panel_) throw std::runtime_error("new_panel failed\n");
	if (parent_)
	{
		::move_panel(panel_, parent_->y(), parent_->x()); //move to default position relative to father
		parent_->add_child(this); //append itself to the father
	}
	hide(); //hide widget by default
}

ncurses::panel::~panel()
{
	if (parent_) parent_->del_child(this); //remove child from the parent's list
	::del_panel(panel_);
}

void ncurses::panel::add_child(panel *item)
{
	childs_.push_back(item); //append a new child to the list
}

void ncurses::panel::del_child(panel *item)
{
	childs_.erase(std::remove(childs_.begin(),
					  childs_.end(),
					  item), childs_.end());
}

void ncurses::panel::top()
{
	if (hidden()) return; //we should skip this function if panel hidden
	NCURSES_ASSERT(::top_panel(panel_));
	std::for_each(childs_.begin(), childs_.end(), std::mem_fun(&panel::top));
}

void ncurses::panel::bottom()
{
	if (hidden()) return; //we should skip this function if panel hidden
	NCURSES_ASSERT(::bottom_panel(panel_));
	std::for_each(childs_.begin(), childs_.end(), std::mem_fun(&panel::bottom));
}

void ncurses::panel::show()
{
	 //we should skip this function if panel already visible
	if (hidden()) NCURSES_ASSERT(::show_panel(panel_));
	std::for_each(childs_.begin(), childs_.end(), std::mem_fun(&panel::show));
}

void ncurses::panel::hide()
{
	//we should skip this function if panel already hidden
	if (!hidden()) NCURSES_ASSERT(::hide_panel(panel_));
	std::for_each(childs_.begin(), childs_.end(), std::mem_fun(&panel::hide));
}

bool ncurses::panel::hidden() const
{
	return (::panel_hidden(panel_) == TRUE);
}

bool ncurses::panel::higher(const panel& other) const
{
    PANEL *below = panel_;
    while ((below=panel_below(below))!=0)
    {
	if (below == other.panel_) return true;
    }
    return false;
}

void ncurses::panel::draw()
{}

void ncurses::panel::prepare()
{
	draw();
	std::for_each(childs_.begin(), childs_.end(), std::mem_fun(&panel::prepare));
}

void ncurses::panel::visualize()
{
	prepare();
	show();
}

void ncurses::panel::move(int x_, int y_, coords_type type)
{
	//safe difference
	int diffx = x_ - x();
	int diffy = y_ - y();
	const bool abs_type = (absolute == type);
	::move_panel(panel_, abs_type ? y_ : y() + y_, abs_type ? x_ : x() + x_);

	//childs_ always moving in relative coordinates
	std::for_each(childs_.begin(),
		      childs_.end(),
		      move_to(abs_type ? diffx : x_, abs_type ? diffy : y_));
}

